package com.example.demo.entity;

import com.alibaba.fastjson.annotation.JSONField;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author rqian
 */
@Entity
@Table(name = "USER")
public class UserEntity implements Serializable, UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long             id;
    @NotBlank
    @Size(min = 3, max = 20)
    private String           username;
    @NotBlank
    private String           password;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(
            name = "user_role",
            joinColumns = {
                    @JoinColumn(name = "user_id")
            },
            inverseJoinColumns = {
                    @JoinColumn(name = "role_id")
            }
    )
    private List<RoleEntity> roles;



    /**
     * @return the id
     */
    public long getId() {
        return id;
    }



    /**
     * @param id
     *         the id to set
     */
    public void setId(final long id) {
        this.id = id;
    }



    /**
     * @param username
     *         the username to set
     */
    public void setUsername(final String username) {
        this.username = username;
    }



    /**
     * @param password
     *         the password to set
     */
    public void setPassword(final String password) {
        this.password = password;
    }



    /**
     * @return the roles
     */
    public List<RoleEntity> getRoles() {
        return roles;
    }



    /**
     * @param roles
     *         the roles to set
     */
    public void setRoles(final List<RoleEntity> roles) {
        this.roles = roles;
    }



    @JSONField(serialize = false, deserialize = false)
    @Override public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = new ArrayList<>();
        List<RoleEntity> roles = this.getRoles();
        for (RoleEntity role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getRoleName()));
        }
        return authorities;
    }



    public void setEncodePassword(String password) {
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodePasswd = encoder.encode(password);
        this.password = encodePasswd;
    }



    @Override public String getPassword() {
        return this.password;
    }



    @Override public String getUsername() {
        return this.username;
    }



    @JSONField(serialize = false, deserialize = false)
    @Override public boolean isAccountNonExpired() {
        return true;
    }



    @JSONField(serialize = false, deserialize = false)
    @Override public boolean isAccountNonLocked() {
        return true;
    }



    @JSONField(serialize = false, deserialize = false)
    @Override public boolean isCredentialsNonExpired() {
        return true;
    }



    @JSONField(serialize = false, deserialize = false)
    @Override public boolean isEnabled() {
        return true;
    }
}
